package nova

import (
	"errors"
	"reflect"
	"strings"

	"github.com/go-xorm/xorm"
)

// 此操作只用做后台查询，切勿对外接口，应用了反射，如需使用，请改为switch
func SqlBuilder(xs *xorm.Session, s []map[string]string) error {
	if len(s) < 1 {
		return errors.New("请传入对应的参数")
	}
	for _, vs := range s {
		k, ok1 := vs["k"]
		v, ok2 := vs["v"]
		op, ok3 := vs["op"]
		if !ok1 || !ok3 || k == "" {
			continue
		}
		if !ok2 {
			v = ""
		}
		op = strings.ToLower(op)
		m, ok := method[op]
		if !ok {
			continue
		}
		f := reflect.ValueOf(m.W)
		in := make([]reflect.Value, 4)
		in[0] = reflect.ValueOf(xs)
		in[1] = reflect.ValueOf(m.T)
		in[2] = reflect.ValueOf(k)
		in[3] = reflect.ValueOf(v)
		f.Call(in)
	}
	return nil
}

var (
	method = map[string]wFunc{
		"eq": wFunc{
			W: compare,
			T: "=",
		},
		"neq": wFunc{
			W: compare,
			T: "<>",
		},
		"gt": wFunc{
			W: compare,
			T: ">",
		},
		"egt": wFunc{
			W: compare,
			T: ">=",
		},
		"lt": wFunc{
			W: compare,
			T: "<",
		},
		"elt": wFunc{
			W: compare,
			T: "<=",
		},
		"likeleft": wFunc{
			W: like,
			T: "left",
		},
		"likeright": wFunc{
			W: like,
			T: "right",
		},
		"likeall": wFunc{
			W: like,
			T: "all",
		},
		"in": wFunc{
			W: in,
			T: "in",
		},
		"between": wFunc{
			W: between,
			T: "between ? and ?",
		},
		"orderby": wFunc{
			W: orderby,
			T: "asc",
		},
		"orderbydesc": wFunc{
			W: orderby,
			T: "desc",
		},
	}
)

type wFunc struct {
	W interface{}
	T string
}

func compare(xs *xorm.Session, op, k, v string) {
	key := "`" + k + "`" + op + "?"
	xs.Where(key, v)
	return
}

func like(xs *xorm.Session, op, k, v string) {
	wl := v
	switch op {
	case "left":
		wl = "%" + wl
	case "right":
		wl = wl + "%"
	case "all":
		wl = "%" + wl + "%"
	default:
		return
	}
	key := "`" + k + "`" + " like ?"
	xs.Where(key, wl)
	return
}

func in(xs *xorm.Session, op, k, v string) {
	s := strings.Split(v, ",")
	ss := make([]interface{}, len(s))
	for _, v1 := range s {
		ss = append(ss, v1)
	}
	xs.In("`"+k+"`", ss...)
	return
}

func between(xs *xorm.Session, op, k, v string) {
	key := "`" + k + "`" + " " + op
	s := strings.Split(v, ",")
	if len(s) != 2 {
		return
	}
	xs.Where(key, s[0], s[1])
	return
}

func orderby(xs *xorm.Session, op, k, v string) {
	switch op {
	case "asc":
		xs.Asc("`" + k + "`")
	case "desc":
		xs.Desc("`" + k + "`")
	default:
		xs.Desc("id")
	}
	return
}
